/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.gui.widgets;

import dgbgui.gui.widgets.visual.QueryWidget;
import dgbgui.gui.widgets.visual.definition.BooleanDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.ClosureDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.ConceptTypeDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.ConceptTypesDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.CustomDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.DefinitionWidget;
import dgbgui.gui.widgets.visual.definition.FilteredConceptDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.FilteredLayerDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.FilteredRelationDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.LayerTypesDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.NeighbourhoodDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.NotDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.PathDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.RelationTypesDefinitionWidget;
import dgbgui.gui.widgets.visual.definition.ResultsDefinitionWidget;
import dgbgui.gui.widgets.visual.modeldriven.ModelDrivenConceptWidget;
import dgbgui.gui.widgets.visual.modeldriven.ModelGraphWidget;
import dgbgui.gui.widgets.visual.results.ConceptInstanceResultWidget;
import dgbgui.gui.widgets.visual.results.ConceptTypeResultWidget;
import dgbgui.gui.widgets.visual.results.GraphResultWidget;
import dgbgui.gui.widgets.visual.results.LayerInstanceResultWidget;
import dgbgui.gui.widgets.visual.results.LayerTypeResultWidget;
import dgbgui.gui.widgets.visual.results.RelationInstanceResultWidget;
import dgbgui.gui.widgets.visual.results.RelationTypeResultWidget;
import dgbgui.gui.widgets.visual.results.ResultWidget;
import dgbgui.gui.widgets.visual.results.ResultsWidget;
import dgbgui.modeldocument.DGBModel;
import dgbgui.modeldocument.Query;
import dgbgui.modeldocument.QueryResult;
import dgbgui.modeldocument.definition.BooleanDefinition;
import dgbgui.modeldocument.definition.ClosureDefinition;
import dgbgui.modeldocument.definition.ConceptTypeDefinition;
import dgbgui.modeldocument.definition.ConceptTypesDefinition;
import dgbgui.modeldocument.definition.CustomDefinition;
import dgbgui.modeldocument.definition.Definition;
import dgbgui.modeldocument.definition.FilteredConceptDefinition;
import dgbgui.modeldocument.definition.FilteredLayerDefinition;
import dgbgui.modeldocument.definition.FilteredRelationDefinition;
import dgbgui.modeldocument.definition.LayerTypesDefinition;
import dgbgui.modeldocument.definition.NeighbourhoodDefinition;
import dgbgui.modeldocument.definition.NotDefinition;
import dgbgui.modeldocument.definition.PathDefinition;
import dgbgui.modeldocument.definition.RelationTypesDefinition;
import dgbgui.modeldocument.definition.ResultsDefinition;
import dgbgui.modeldocument.primitives.Concept;
import dgbgui.modeldocument.primitives.ConceptType;
import dgbgui.modeldocument.primitives.Graph;
import dgbgui.modeldocument.primitives.Layer;
import dgbgui.modeldocument.primitives.LayerType;
import dgbgui.modeldocument.primitives.Primitive;
import dgbgui.modeldocument.primitives.Relation;
import dgbgui.modeldocument.primitives.RelationType;
import edu.umd.cs.piccolo.PNode;

public class WidgetFactory { 

    /**
     * @param parent The parnet widget/PNode
     * @param query The query to create a widget for
     * @param nested If the query id a nested query
     * @return the new widget
     */
    static public QueryWidget createWidget(PNode parent, Query query, boolean isRootQuery) {
        QueryWidget widget = new QueryWidget(parent,query);
        // Only add the the widget store if it's a root query
        if ( isRootQuery ) {
            WidgetStore.getInstance().addWidget(query,widget);
        }   
        return widget;
    }
    
    /**
     * @param parent The parnet widget/PNode
     * @param query The query to create a widget for
     * @return the new widget
     */
    static public QueryWidget createWidget(PNode parent, Query query) {
        // By default, query widgets are nested widgets, and should not
        // be added to the widget store
        return createWidget(parent,query,false);
    }
    
    static public DefinitionWidget createWidget(PNode parent, Definition definition) {
        // ------------ Concept types and sets -----------
        if ( definition instanceof ConceptTypesDefinition ) {
            return new ConceptTypesDefinitionWidget(parent, (ConceptTypesDefinition)definition );
        }
        if ( definition instanceof ConceptTypeDefinition ) {
            return new ConceptTypeDefinitionWidget(parent, (ConceptTypeDefinition)definition );
        }
        if ( definition instanceof FilteredConceptDefinition ) {
            return new FilteredConceptDefinitionWidget(parent, (FilteredConceptDefinition)definition );
        }
        // ------------- Relation types and sets -----------
        if ( definition instanceof RelationTypesDefinition ) {
            return new RelationTypesDefinitionWidget(parent, (RelationTypesDefinition)definition );
        }
        if ( definition instanceof FilteredRelationDefinition ) {
            return new FilteredRelationDefinitionWidget(parent, (FilteredRelationDefinition)definition );
        }
        // ------------- Layer types and sets -----------
        if ( definition instanceof LayerTypesDefinition ) {
            return new LayerTypesDefinitionWidget(parent, (LayerTypesDefinition)definition );
        }
        if ( definition instanceof FilteredLayerDefinition ) {
            return new FilteredLayerDefinitionWidget(parent, (FilteredLayerDefinition)definition );
        }
        // ------------- Other ---------
        if ( definition instanceof BooleanDefinition ) {
            if ( definition instanceof NotDefinition ) {
                // Not is a special case
                return new NotDefinitionWidget(parent, (NotDefinition)definition );
            } else {
                return new BooleanDefinitionWidget(parent, (BooleanDefinition)definition );
            }
        }
        if ( definition instanceof PathDefinition ) {
            return new PathDefinitionWidget(parent, (PathDefinition)definition);
        }
        if ( definition instanceof CustomDefinition ) {
            return new CustomDefinitionWidget(parent, (CustomDefinition)definition);
        }
        
        if ( definition instanceof ResultsDefinition ) {
            return new ResultsDefinitionWidget(parent, (ResultsDefinition)definition);
        }
        
        if ( definition instanceof NeighbourhoodDefinition ) {
            return new NeighbourhoodDefinitionWidget(parent, (NeighbourhoodDefinition)definition);
        } 
        
        if ( definition instanceof ClosureDefinition ) {
            return new ClosureDefinitionWidget(parent, (ClosureDefinition)definition);
        }

        
        // A new definition? No gui representation of the definition
        assert false;
        return null;
    }
    
    static public ResultsWidget createWidget(PNode parent, QueryResult result) {
        return new ResultsWidget(parent,result);
    }
    
    static public ResultWidget createWidget(PNode parent, Primitive primitive) {
        ResultWidget widget = null;
        if ( primitive instanceof ConceptType ) {
            widget = new ConceptTypeResultWidget(parent,(ConceptType)primitive);
        }
        else if ( primitive instanceof RelationType ) {
            widget = new RelationTypeResultWidget(parent,(RelationType)primitive);
        }
        else if ( primitive instanceof LayerType ) {
            widget = new LayerTypeResultWidget(parent,(LayerType)primitive);
        }
        else if ( primitive instanceof Concept ) {
            widget = new ConceptInstanceResultWidget(parent,(Concept)primitive);
        }
        else if ( primitive instanceof Relation ) {
            widget = new RelationInstanceResultWidget(parent,(Relation)primitive);
        }
        else if ( primitive instanceof Layer ) {
            widget = new LayerInstanceResultWidget(parent,(Layer)primitive);
        }
        else if ( primitive instanceof Graph ) {
            widget = new GraphResultWidget(parent,(Graph)primitive);
        }
        else {
            // Must be a widget for each primitive that can be visually represented
            assert false;
        }
        
        WidgetStore.getInstance().addWidget(primitive, widget);
        return widget;
    }
    
    static public ModelGraphWidget createWidget(PNode parent, DGBModel model) {
        // Create the graph widget
        ModelGraphWidget widget = new ModelGraphWidget(parent,model);
        return widget;
    }
    

    static public ModelDrivenConceptWidget createModelDrivenWidget(PNode parent, Concept concept, Query query, boolean isTarget) {
        
        ModelDrivenConceptWidget widget = new ModelDrivenConceptWidget(parent,concept,query,isTarget);
        WidgetStore.getInstance().addWidget(concept,widget);
        return widget;
    }

    
}